package com.atguigu.gmall.product.service.impl;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.search.SearchFeignClient;
import com.atguigu.gmall.item.to.CategoryView;
import com.atguigu.gmall.product.entity.*;
import com.atguigu.gmall.product.service.*;
import com.atguigu.gmall.product.vo.SaveSkuVo;
import com.atguigu.gmall.search.Goods;
import com.atguigu.gmall.search.SearchAttr;
import com.atguigu.starter.cache.service.BitmapService;
import com.atguigu.starter.cache.service.CacheService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.atguigu.gmall.product.mapper.SkuInfoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
* @author vvx
* @description 针对表【sku_info(库存单元表)】的数据库操作Service实现
* @createDate 2023-08-15 18:49:15
*/
@Service
@Slf4j
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo>
    implements SkuInfoService{

    @Autowired
    SkuInfoService skuInfoService;
    @Autowired
    SkuImageService skuImageService;
    @Autowired
    SkuAttrValueService skuAttrValueService;
    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    BitmapService bitmapService;


//    要在启动类上开启@EnableFeignClients(basePackages = "com.atguigu.gmall.feign.search")
//    不然不能自动注入
    @Autowired
    SearchFeignClient searchFeignClient;
    @Autowired
    ThreadPoolExecutor executor;
    @Autowired
    BaseTrademarkService baseTrademarkService;
    @Autowired
    BaseCategory1Service baseCategory1Service;
    @Autowired
    CacheService cacheService;

    @Override
    public void saveSkuInfo(SaveSkuVo vo) {

/*
* todo:
*  1 基本信息
* 2 sku图片
* 3 保存sku的平台属性名和值
* 4 保存sku的平台属性名和值
* */

//        1
        SkuInfo skuInfo = new SkuInfo();
        BeanUtils.copyProperties(vo, skuInfo);
        save(skuInfo);
        Long id = skuInfo.getId();

//        2
        List<SkuImage> skuImages = vo.getSkuImageList()
                .stream()
                .map(item -> {
                    SkuImage skuImage = new SkuImage();
                    skuImage.setSkuId(id);
                    skuImage.setImgName(item.getImgName());
                    skuImage.setImgUrl(item.getImgUrl());
                    skuImage.setSpuImgId(item.getSpuImgId());
                    skuImage.setIsDefault(item.getIsDefault());
                    return skuImage;
                }).collect(Collectors.toList());
        skuImageService.saveBatch(skuImages);


//        3
        List<SkuAttrValue> skuAttrValues = vo.getSkuAttrValueList()
                .stream()
                .map(item -> {
                    SkuAttrValue attrValue = new SkuAttrValue();
                    attrValue.setAttrId(item.getAttrId());
                    attrValue.setValueId(item.getValueId());
                    attrValue.setSkuId(id);
                    return attrValue;
                }).collect(Collectors.toList());
        skuAttrValueService.saveBatch(skuAttrValues);


        //4
        List<SkuSaleAttrValue> skuSaleAttrValues = vo.getSkuSaleAttrValueList().stream()
                .map(item -> {
                    SkuSaleAttrValue saleAttrValue = new SkuSaleAttrValue();
                    saleAttrValue.setSkuId(id);
                    saleAttrValue.setSpuId(vo.getSpuId());
                    saleAttrValue.setSaleAttrValueId(item.getSaleAttrValueId());
                    return saleAttrValue;
                }).collect(Collectors.toList());
        skuSaleAttrValueService.saveBatch(skuSaleAttrValues);

    }


//    不会写
//    重点！！！！！！！！！！！！
//    初始化SKU的位图
    @Override
    public void initSkuIdsBitMap() {

//        查询所有skuid
        List<Long> skuIds = lambdaQuery()
                .select(SkuInfo::getId)
                .list()
                .stream()
//                为什么不用item？？？
                .map(SkuInfo::getId)
                .collect(Collectors.toList());


//        初始化位图
        skuIds.forEach(
//                在位图中占位
                item -> {
                    redisTemplate.opsForValue().setBit(RedisConst.BITMAP_SKUIDS,item,true);
                }
        );

        log.info("位图初始化完成：总计商品：【{}】 件",skuIds.size());
    }


    //      准备远程检索用的商品数据 给searchFeignClient用
    private Goods prepareGoods(Long skuId) {

        Goods goods = new Goods();
//        goods.setId();
//        goods.setDefaultImg();
//        goods.setTitle();
//        goods.setPrice();
//        goods.setCreateTime();

//

//        基本数据Skuinfo
        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfo skuInfo = skuInfoService.getById(skuId);
            goods.setId(skuInfo.getId());
            goods.setId(skuInfo.getId());
            goods.setDefaultImg(skuInfo.getSkuDefaultImg());
            goods.setTitle(skuInfo.getSkuName());
            goods.setPrice(skuInfo.getPrice());
            goods.setCreateTime(new Date());
            return skuInfo;
        }, executor);


//        goods.setTmId();
//        goods.setTmName();
//        goods.setTmLogoUrl();

//        品牌数据，baseTrademarkService
        CompletableFuture<Void> trademarkFuture = skuInfoFuture.thenAcceptAsync(item -> {

//            查找品牌的id
            BaseTrademark trademark = baseTrademarkService.getById(item.getTmId());
            goods.setTmId(item.getTmId());
            goods.setTmName(trademark.getTmName());
            goods.setTmLogoUrl(trademark.getLogoUrl());
        }, executor);

//        goods.setCategory1Id();
//        goods.setCategory1Name();
//        goods.setCategory2Id();
//        goods.setCategory2Name();
//        goods.setCategory3Id();
//        goods.setCategory3Name();
//        goods.setHotScore();

//        分类数据 baseCategory1Service
        CompletableFuture<Void> categoryViewFuture = skuInfoFuture.thenAcceptAsync(item -> {
            CategoryView categoryView = baseCategory1Service.getCategoryView(item.getCategory3Id());
            goods.setCategory1Id(categoryView.getCategory1Id());
            goods.setCategory1Name(categoryView.getCategory1Name());
            goods.setCategory2Id(categoryView.getCategory2Id());
            goods.setCategory2Name(categoryView.getCategory2Name());
            goods.setCategory3Id(categoryView.getCategory3Id());
            goods.setCategory3Name(categoryView.getCategory3Name());
            goods.setHotScore(0L);
        }, executor);


//        当前品牌的属性名和值
//        goods.setAttrs();

        CompletableFuture<Void> attrFuture = CompletableFuture.runAsync(() -> {
            List<SearchAttr> attrs = skuAttrValueService.getSkuAttrAndValue(skuId);
            goods.setAttrs(attrs);
        }, executor);

        CompletableFuture.allOf(trademarkFuture,categoryViewFuture,attrFuture)
                .join();


        return goods;
    }


    @Override
    public void onSale(Long skuId) {

//        1 数据库
        skuInfoService.lambdaUpdate()
                .set(SkuInfo::getIsSale, 1)
                .eq(SkuInfo::getId, skuId)
                .update();

//        2 位图
        bitmapService.setbit(RedisConst.BITMAP_SKUIDS,skuId,true);

//        3 es
//        查goods数据
        Goods goods = prepareGoods(skuId);
        searchFeignClient.saveGoods(goods);
    }

    @Override
    public void cancelSale(Long skuId) {

//      1  数据库
        skuInfoService.lambdaUpdate()
                .set(SkuInfo::getIsSale, 0)
                .eq(SkuInfo::getId, skuId)
                .update();

//        2 删除位图
        bitmapService.setbit(RedisConst.BITMAP_SKUIDS,skuId,false);

//        3 es删除
        searchFeignClient.delete(skuId);

//        4 缓存删除
//        延迟双删
        cacheService.delayDoubleDel(RedisConst.SKU_INFO_CACHE_KEY+skuId,10L);

//
//        //下架：更新数据库
//        boolean update = lambdaUpdate()
//                .set(SkuInfo::getIsSale, 0)
//                .eq(SkuInfo::getId, skuId)
//                .update();
//
//
//        //下架的商品要从位图移除
//        bitmapService.setbit(RedisConst.BITMAP_SKUIDS,skuId,false);
//
//        //把这个商品的数据从ES中移除
//        searchFeignClient.delete(skuId);
//
//
//        //【业务保证数据最终一致性】
//        //删除redis中缓存的sku数据
//        cacheService.delayDoubleDel(RedisConst.SKU_INFO_CACHE_KEY+skuId,10L);
    }
}




